<template>
  <div class="showMark">
    <div class="markdown-body" v-highlight v-html="htmlText" ref="aContent"></div>
  </div>
</template>

<script>
import showdown from "showdown";

export default {
  props: ['text'],
  data() {
    return {
      tocData: '',
      flag: true,
      htmlText: '',
    }
  },
  watch: {
    text: {
      deep: true,
      immediate: true, //是否刚进来初始化就加载
      handler(value) {
        this.initPage()
      },
    }
  },
  methods: {
    initPage() {
      let converter = new showdown.Converter();
      // 显示表格
      converter.setOption("tables", true);
      this.htmlText = converter.makeHtml(this.text);
      this.makeToc();
    },
    hit(info) {
      this.$emit('btnClick', info) //报告!!触发btnClick , 传递参数"123"
    },
    // 将一个集合的数据变成一个树形的数据结构
    toTree(data) {
      // 删除 所有 children,以防止多次调用
      data.forEach(function (item) {
        delete item.children;
      });

      // 将数据存储为 以 id 为 KEY 的 map 索引数据列
      var map = {};
      data.forEach(function (item) {
        map[item.id] = item;
      });
      var val = [];
      data.forEach(function (item) {
        // 以当前遍历项的pid,去map对象中找到索引的id
        var parent = map[item.p_id];
        // 好绕啊，如果找到索引，那么说明此项不在顶级当中,那么需要把此项添加到，他对应的父级中
        if (parent) {
          (parent.children || (parent.children = [])).push(item);
        } else {
          //如果没有在map中找到对应的索引ID,那么直接把 当前的item添加到 val结果集中，作为顶级
          val.push(item);
        }
      });
      return val;
    },
    /**
     * 生成目录
     * */
    makeToc() {
      // 获取所有的h标签，给他们加上id，同时创建符合toTree方法要求的对象
      //{
      //          id:'',// 抛出id
      //           tag:'',// 抛出标签名称
      //          label:'',// 抛出标题
      //          p_id:'',// 抛出父级id
      // }

      // 定义参与目录生成的标签
      const tocTags = ["H1", "H2", "H3", "H4", "H5", "H6"];

      // 目录树结果
      const tocArr = [];

      this.$nextTick(() => {
        // 获取所有标题标签
        const headDoms = Array.from(this.$refs.aContent.childNodes).filter(item => tocTags.includes(item.tagName));
        // 遍历标题标签
        headDoms.forEach((item, index, arr) => {
          // 给标题添加id
          item.id = `h-${index + 1}`;
          // 获取当前节点前面的节点
          let prevs = arr.filter((i, j) => j < index);
          // 过滤前面的节点为合理节点
          // 如 h3节点前  只能为 h1 h2 h3
          prevs = prevs.filter(i => tocTags.filter((i, j) => j <= tocTags.findIndex(i => i == item.tagName)).includes(i.tagName));
          // 对前面的节点进行排序，距离自身节点近的排在前面
          // 如 div > p > span > img  当前为img
          // 常规获取节点为 [div,p,span,img]
          // 排序后获取节点为 [img,span,p,div]
          prevs = prevs.sort((a, b) => -(a.id.replace('h-', '')) - b.id.replace('h-', ''));
          // 查询距离自身节点最近的不同于当前标签的节点
          const prev = prevs.find(i => i.tagName != item.tagName);
          this.maxum = Math.max(this.maxum, index + 1)
          tocArr.push({
            id: index + 1,// 抛出id
            tag: item.tagName,// 抛出标签名称
            label: item.innerText,// 抛出标题
            p_id: item.tagName == "H1" || prev == null ? 0 : Number(prev.id.replace("h-", '')),// 抛出父级id
          })
        })
        // 使用上述方法生成树 最后在el-tree的data中使用 tocData即可
        this.tocData = this.toTree(tocArr);
        this.hit(this.tocData)
        // console.log('---', this.tocData)
      })
    },
    updated() {
      // 需要在data里面加上flag，只触发一次里面内容
      if (this.flag) {
        this.makeToc()
        this.flag = false
      }
    },

  },
}
</script>

<style></style>